﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Linq;
using CSImport.WordPress;

namespace CSImport
{
    class WordPressExtRssParser
    {
        public static XNamespace wp = "http://wordpress.org/export/1.0/";
        public static XNamespace dc = "http://purl.org/dc/elements/1.1/";
        public static XNamespace wfw = "http://wellformedweb.org/CommentAPI/";
        public static XNamespace content = "http://purl.org/rss/1.0/modules/content/";

        public XElement rootElement { get; set; }
        public List<Category> categoryList { get; set; }
        public List<Tag> tagList { get; set; }

        public WordPressExtRssParser() { }

        public WordPressExtRssParser(String exRSSXMLFileName)
        {
            this.rootElement = loadDocument(exRSSXMLFileName);
        }

        public XElement loadDocument(String exRSSXMLFileName)
        {
            return XElement.Load(exRSSXMLFileName);
        }

        public List<Category> parseCategories()
        {
            List<Category> categoryList = new List<Category>();
            var categoryElements = rootElement.Element("channel").Elements(wp + "category");

            foreach (XElement item in categoryElements)
            {
                Category category = new Category();
                category.nickName = getValue(item.Element(wp + "category_nickname"));
                category.parentName = getValue(item.Element(wp + "category_parent"));
                category.name = getValue(item.Element(wp + "cat_name"));
                categoryList.Add(category);
            }

            return categoryList;
        }

        public List<Tag> parseTags()
        {
            List<Tag> tagList = new List<Tag>();
            var tagElements = rootElement.Element("channel").Elements(wp + "tag");

            foreach (XElement item in tagElements)
            {
                Tag tag = new Tag();
                tag.slug = getValue(item.Element(wp + "tag_slug"));
                tag.name = getValue(item.Element(wp + "tag_name"));
                tagList.Add(tag);
            }

            return tagList;
        }

        public List<BlogPost> parseBlogPosts()
        {
            List<BlogPost> blogList = new List<BlogPost>();
            var blogElements = rootElement.Element("channel").Elements("item");

            initializeTagList();

            foreach (XElement item in blogElements)
            {
                BlogPost post = new BlogPost();
                post.title = getValue(item.Element("title"));
                post.directLink = getValue(item.Element("link"));
                post.postId = getValue(item.Element(wp + "post_id"));
                post.publicationDate = parseDateTimeStr(getValue(item.Element("pubDate")));
                post.creator = getValue(item.Element(dc + "creator"));
                post.description = getValue(item.Element("description"));
                post.content = getValue(item.Element(content + "encoded"));
                post.postDate = parseDateTimeStr(getValue(item.Element(wp + "post_date")));
                post.postDateGMT = parseDateTimeStr(getValue(item.Element(wp + "post_date_gmt")));
                post.commentStatus = getValue(item.Element(wp + "comment_status"));
                post.postName = getValue(item.Element(wp + "post_name"));
                post.status = getValue(item.Element(wp + "status"));
                post.parentId = getValue(item.Element(wp + "post_parent"));
                post.menuOrder = getValue(item.Element(wp + "menu_order"));
                post.postType = getValue(item.Element(wp + "post_type"));
                post.postPassword = getValue(item.Element(wp + "post_password"));

                post.category = lookupCategoryByName(getValue(item.Element("category")));



                blogList.Add(post);
            }

            return blogList;
        }

        public String getValue(XElement element)
        {
            if (element == null)
                return "";
            else
                return element.Value;
        }

        public DateTime parseDateTimeStr(String dateTimeStr)
        {
            DateTime dt;
            if (!DateTime.TryParse(dateTimeStr, out dt))
            {
                return new DateTime();
            }
            else
            {
                return dt;
            }
        }

        public Category lookupCategoryByName(String categoryName)
        {
            if (categoryName == null)
                return null;

            if (categoryList == null || categoryList.Count < 1)
                return null;

            foreach (Category cat in categoryList)
            {
                if (categoryName.Equals(cat.name))
                    return cat;
            }

            return null;
        }

        public Tag lookupTagByName(string tagName)
        {
            if (tagName == null)
                return null;

            if (tagList == null || tagList.Count < 1)
                return null;

            foreach (Tag tag in tagList)
            {
                if (tagName.Equals(tag.name))
                    return tag;
            }

            return null;
        }

        internal void initializeTagList()
        {
            if (tagList == null)
            {
                tagList = new List<Tag>();
            }

            return;
        }

        /*
         * Parse through one or more <category ...> elements and determine which 
         * Category object to tag the item with.  Category objects are looked up in the 
         * this.categoryList list.
         */
        internal Category parseItemCategory(IEnumerable<XElement> categoryElements)
        {
            foreach (XElement categoryElement in categoryElements)
            {
                if (!categoryElement.HasAttributes)
                {
                    //if the category element doesn't have any attributes, it won't have a domain
                    //attribute indicating that its a tag
                    return lookupCategoryByName(getValue(categoryElement));
                }
            }

            return null;
        }
    }
}